package com.vf.admin.common;

import cn.hutool.core.util.ObjectUtil;
import com.google.common.base.Strings;
import com.vf.admin.client.common.ClientConstants;
import com.vf.admin.client.common.RedisKeys;
import com.vf.admin.client.service.AppUserService;
import com.vf.admin.common.entity.Result;
import com.vf.admin.common.redis.RedisUtil;
import com.vf.admin.miaodong.entity.AppUser;
import com.vf.admin.platform.entity.Api;
import com.vf.admin.platform.entity.Element;
import com.vf.admin.platform.service.ApiService;
import com.vf.admin.platform.service.ElementService;
import com.vf.admin.utils.ResPonseRetUtil;
import com.vf.admin.utils.StringEx;
import com.vf.admin.utils.ip.IpUtils;
import com.vf.admin.utils.wxpay.MD5Util;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.*;

import static com.vf.admin.utils.StringEx.isNull;

/**
 * 权限拦截过滤
 */
@Component
@Slf4j
public class PerMissInterceptor implements HandlerInterceptor {
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    ElementService elementService;
    @Autowired
    private ApiService apiService;
    @Autowired
    private AppUserService appUserService;
    @Resource
    RedisUtil redisUtil;

    //Controller方法处理之前
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String ip = request.getRemoteHost();
        String contentType = request.getContentType();
        String requestURI = request.getRequestURI();
        String method = request.getMethod();
        String rqtype = request.getHeader("rqtype");
        rqtype = rqtype == null ? "" : rqtype;
        if (StringEx.isNotNull(method) && method.toUpperCase().trim().equals("OPTIONS")) {
            return true;
        }


        //*****************************  参数加密验证 ****************************************//
        /*Integer i = 0;
        for (Object interfaceUrl : Constants.CHECKLIST) {
            String url = interfaceUrl.toString();
            log.info("---------------需要加密验证的接口:------------------" + url);
            if (url.equals(requestURI)) {
                i = 1;
                break;
            }
        }
        if (i.equals(1)) {
            SortedMap<String, String> map = new TreeMap<>();
            Map<String, String[]> maps = request.getParameterMap();
            for (Map.Entry<String, String[]> entry : maps.entrySet()) {
                map.put(entry.getKey(), entry.getValue()[0]);
            }
            if (checkSign(map)) return false;

        }*/



        //*****************************  拦截后台API接口 ****************************************
        //获取所有后台的API地址
        if (Constants.platformApiCacheMap.size() <= 0) {
            Map<String, Object> paraMap = new HashMap<String, Object>();
            List<Element> list = elementService.findList(paraMap);
            if (list != null && list.size() > 0) {
                for (Element element : list) {
                    Constants.platformApiCacheMap.put(element.getLinks(), 1);
                }
            }
        }
        //判断访问的路径是不是API地址
        if (Constants.platformApiCacheMap.get(requestURI) != null && Constants.platformApiCacheMap.get(requestURI).intValue() == 1) {
            //判断是否已经登录
            HttpSession sessionObj = request.getSession(false);
            if (sessionObj == null) {
                loginOut(rqtype, request, response);
                return false;
            }
            Object userObj = sessionObj.getAttribute(Constants.access_token);
            if (userObj == null) {
                loginOut(rqtype, request, response);
                return false;
            }
            //判断当前登录用户是否拥有该API的权限
//            User user = (User) userObj;
//            Map<String, Integer> userCacheMap = user.getUserCacheMap();
//            if (userCacheMap == null || userCacheMap.get(requestURI) == null || userCacheMap.get(requestURI).intValue() != user.getId()) {
//                loginOut(rqtype, request, response);
//                return false;
//            }
        }
        //获取所有客户端的API地址
        if (Constants.ClientApiCacheMap.size() <= 0) {
            Map<String, Object> paraMap = new HashMap<String, Object>();
            paraMap.put("apitype", Constants.API_CLIENTTYPE_GEREN);
            paraMap.put("loginstate", 1);
            List<Api> list = apiService.findList(paraMap, null);
            if (list != null && list.size() > 0) {
                for (Api api : list) {
                    Constants.ClientApiCacheMap.put(api.getApiurl(), Constants.API_CLIENTTYPE_GEREN);
                }
            }
        }
        //判断访问的路径是不是API地址
        if (Constants.ClientApiCacheMap.get(requestURI) != null) {
            //判断是否已经登录
            Object headerObj = request.getHeader(ClientConstants.client_toke);
            if (isNull(headerObj)) {
                Result result = new Result();
                result.setCode(Constants.code_login_error);
                result.setMsg(Constants.msg_return_login);
                ResPonseRetUtil.getInstance().sendJsonMessage(response, result);
                return false;
            }
            Object userIdObj = redisUtil.get(RedisKeys.userToken + headerObj.toString());


            if (StringEx.isNotNull(headerObj)) {

                AppUser appUser = appUserService.get(Integer.valueOf(userIdObj.toString()));
                if (appUser.getStates() == Constants.shiFou_STATE_FOU) {
                    Result result = new Result();
                    result.setCode(Constants.code_login_error);
                    result.setMsg(Constants.msg_return_login);
                    ResPonseRetUtil.getInstance().sendJsonMessage(response, result);
                    return false;
                }

            }

            if (StringEx.isNotNull(headerObj)) {
                if (isNull(userIdObj)) {
                    Result result = new Result();
                    result.setCode(Constants.code_login_error);
                    result.setMsg(Constants.msg_return_login);
                    ResPonseRetUtil.getInstance().sendJsonMessage(response, result);
                    return false;
                } else {
                    Integer userId = (Integer) redisUtil.get(RedisKeys.userToken + request.getHeader(ClientConstants.client_toke));
                    if (!isNull(userId)) {
                        AppUser user = appUserService.getFromDB(userId);
                        if (user == null) {
                            return false;
                        }
                        //用户不在直播中
                        if (user.getOnlinestatus() != 0) {
                            //即为在线
                            appUserService.onlineUpstate(user.getId(), 1);
                            //是否在线 redis 设置过期时间
                            if (ObjectUtil.isNotEmpty(userId)) {
                                String key = String.format(RedisKeys.onlines, userId);
                                redisUtil.set(key, true, 600);
                            }
                        }

                    }
                }
            }
        }
        return true;
    }

    /**
     * 登录失效
     *
     * @param rqtype
     * @param request
     * @param response
     * @throws Exception
     */
    public void loginOut(String rqtype, HttpServletRequest request, HttpServletResponse response) throws Exception {
        if (rqtype.contains("json")) {
            Result result = new Result();
            result.setCode(Constants.code_login_error);
            result.setMsg(Constants.msg_return_permissions);
            ResPonseRetUtil.getInstance().sendJsonMessage(response, result);
        } else {
            response.setContentType("text/html; charset=UTF-8");
            ServletOutputStream writer = response.getOutputStream();
//            writer.write("<script>if (top != self) {parent.top.window.location.reload();}else{window.location='/web/loginout.html';}</script>".getBytes("utf-8"));
            writer.write("<script>window.location='/web/loginout.html';</script>".getBytes("utf-8"));
            writer.close();
            response.flushBuffer();

            // 不存在重定向到错误页面，并返回 false
//                   response.sendRedirect(request.getContextPath()+"/web/login.html");
        }
    }

    //Controller方法处理完之后，DispatcherServlet进行视图的渲染之前，也就是说在这个方法中你可以对ModelAndView进行操作
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        Object msg = request.getAttribute("msg");
        Object url = request.getAttribute("url");
        Object data = request.getAttribute("data");

//        System.out.println("path:"+request.getServletContext().getContextPath());
//        System.out.println("msg:"+msg);
//        System.out.println("url:"+url);
//        System.out.println("data:"+data);
//        logger.info("Controller方法处理完之后...........");
    }

    //DispatcherServlet进行视图的渲染之后
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
//        logger.info("DispatcherServlet进行视图的渲染之后...........");
//        response.setHeader("erroeMsgs", java.net.URLEncoder.encode("失败原因","UTF-8"));
//        Object objUrl = request.getAttribute("URL");
//        System.out.println("进行视图的渲染之后:"+objUrl);
    }

    /**
     * 接口签名验证
     *
     * @param map
     * @return
     */
    public Boolean checkSign(SortedMap<String, String> map) {
        if (map != null) {
            if (map.get("sign") == null || map.get("sign").equals("")) return true;
            if (map.get("timeStamp") == null || map.get("timeStamp").equals("")) return true;
            String sign = map.get("sign").toUpperCase();
            map.remove("sign");
            String realSign = createSign("utf8", map);
            if (!realSign.equals(sign)) return true;
            return false;
        } else {
            return true;
        }
    }

    private String createSign(String characterEncoding, SortedMap<String, String> parameters) {
        StringBuffer sb = new StringBuffer();
        for (Map.Entry<String, String> entry : parameters.entrySet()) {
            if (!Strings.isNullOrEmpty(entry.getValue()) && !"sign".equals(entry.getKey()) && !"key".equals(entry.getKey())) {
                sb.append(entry.getKey() + "=" + entry.getValue() + "&");
            }
        }
        String s = sb.toString();
        if (s.length() > 0) {
            s = s.substring(0, sb.toString().length() - 1);
        }
        String sign = MD5Util.MD5Encode(s, characterEncoding).toUpperCase();
        return sign;
    }


    public Object errorJSON(String msg) {
        Result result = new Result();
        //result.setData("");
        result.setCode(Constants.code_return_error);
        result.setMsg(msg);
        return result;
    }
}
